import yaml
import fnmatch
class perm:
    def __init__(self):
        self.object = dict()

    # File IO And File Object Init

    def __object_init(self):
        if self.object == None:
            self.object = dict()
            self.object['permission']['list'] = dict()
            self.object['group'] = dict()
            self.object['group']['list'] = dict(list())
            self.object['group']['parent'] = dict()
            self.object['group']['user'] = dict()
            self.object["group"]["permset"] = dict()
            self.object["user"] = dict()
            self.object['permission']['nodeallow'] = dict()
            self.object['permission']['binding'] = dict()

    def read(self, FileName):
        with open(FileName, "rt", encoding='utf-8') as this:
            self.object = yaml.load(this.read())
        self.__object_init()

    def dump(self, FileName):
        with open(FileName, "w", encoding='utf-8') as this:
            yaml.dump(self.object, this)

    # File IO And File Object Init

    # About Nornal Perm

    def AddPermNode(self, key, PermNodeName):
        if key in self.object["permission"]['list'].keys():
            return True
        self.object["permission"]['list'][key] = PermNodeName

    def DelPermNode(self, key):
        if key not in self.object["permission"]['list'].keys():
            return False
        del self.object["permission"]['list'][key]
    
    def GetNodeName_byValue(self, value):
        key = {v: k for k, v in self.object["permission"]['list'].items()}[value]
        return key

    def GetValue(self, key):
        if key in set(self.object["permission"]['list'].keys()):
            return self.object["permission"]['list'][key]
        else:
            return False
    
    def KeyList(self):
        return self.object["permission"]['list'].keys()

    def GetNodeList(self):
        return self.object['permission']['list'].values()

    # About Nornal Perm

    # About Wildcards
    def __re(self, list, permname):
        return fnmatch.filter(list, permname)
    # About Wildcards

    # About Group

    def GroupList(self):
        return self.object["group"]["list"]
    
    def AddGroup(self, GroupName, NodeName):
        if GroupName in self.object["group"]["list"]:
            return False
        else:
            self.object["group"]["list"][GroupName] = "group." + NodeName
            return True if GroupName in set(self.object["group"]["list"].keys()) else False

    def DelGroup(self, GroupName = "", NodeName = ""):
        if GroupName == "" and NodeName == "":
            return False
        elif GroupName == "":
            # Del group at list
            popdict = {v: k for k, v in self.object["group"]["list"].items()}
            if NodeName in set(popdict.keys()):
                key = popdict[NodeName]
                del self.object["group"]["list"][key]

            # Del group at parent
            if key in set(self.object["group"]["parent"].keys()):
                del self.object["group"]["parent"][key]

            # Del user bind group
            for i in self.object["group"]["user"].keys():
                if self.object["group"]["user"][i] == key:
                    del self.object["group"]["user"][i]
            if key not in self.object["group"]["list"]:
                return True
        elif NodeName == "":
            key = GroupName
            if key in set(self.object["group"]["list"].keys()):
                del self.object["group"]["list"][key]

            # Del group at parent
            if key in set(self.object["group"]["parent"].keys()):
                del self.object["group"]["parent"][key]

            # Del user bind group
            for i in self.object["group"]["user"].keys():
                if self.object["group"]["user"][i] == key:
                    del self.object["group"]["user"][i]
            if key not in set(self.object["group"]["list"]):
                return True

    def IsInGroup(self, GroupName, UserName):
        if UserName in set(self.object["group"]["user"].keys()):
            if GroupName == self.object["group"]["user"][UserName]:
                return True
            else:
                return False
        return False

    def WhatGroup(self, UserName):
        if UserName in set(self.object["group"]["user"].keys()):
            return self.object["group"]["user"][UserName]
        else:
            return "default"

    def IsGroup(self, group):
        data = self.GroupList()
        if group in set(data.keys()):
            return True
        if group in set(data.values()):
            return True
        return False

    def DoHaveTheGroup(self, GroupName):
        if GroupName in set(self.object['group']['list'].keys()):
            return True
        else:
            return False

    # About Group

    # About User's Permission
    def AddUser(self, UserName):
        self.object["user"][UserName] = list()

    def DoUserHavePerm(self, NodeName, UserName):
        if UserName not in set(self.object['user'].keys()):
            return False

        if NodeName in set(self.object['user'][UserName]):
            return True
        
        return False

    def GivePermToUser(self, NodeName, UserName):
        if UserName not in set(self.object["user"].keys()):
            self.AddUser(UserName)

        if not False in set(list(a in self.object["user"][UserName] for a in self.__re(self.object['permission']['list'].values(), NodeName))):
            return True

        if False in set(list(a in set(self.object["permission"].values()) for a in self.__re(self.object['permission']['list'].values(), NodeName))):
            return False

        var = list(self.__re(self.object['permission']['list'].values(), NodeName))
        Ivar = list(self.__re(self.object['permission']['list'].values(), NodeName))
        for i in range(len(var)):
            if var[i] in set(self.object['user'][UserName]):
                del Ivar[i]
        #self.object["user"][UserName].append(NodeName)
        self.object["user"][UserName] += Ivar
        return True

    def RemovePermFromUser(self, NodeName, UserName):
        if UserName not in set(self.object["user"].keys()):
            return False

        if NodeName not in set(self.object["user"][UserName]):
            return False

        self.object["user"][UserName].remove(NodeName)
        return True

    # About User's Permission

    # About Group's Parent
    def GetParent(self, Group):
        if Group not in self.object['group']['parent']:
            return False

        return self.object['group']['parent'][Group]

    def AddParent(self, Group, ParentGroup):
        if Group not in self.object['group']['parent']:
            self.object['group']['parent'].setdefault(Group, list())

        if self.IsGroup(Group):
            return False
        
        if self.IsGroup(ParentGroup):
            return False

        if ParentGroup in self.object['group']['parent'][Group]:
            return True

        self.object['group']['parent'][Group].append(ParentGroup)
        return True

    def DelParent(self, Group, ParentGroup):
        if Group not in self.object['group']['parent']:
            return False

        if ParentGroup not in self.object['group']['parent'][Group]:
            return False

        self.object['group']['parent'][Group].remove(ParentGroup)
        return True

    def EraseParent(self, Group):
        if Group not in self.object['group']['parent']:
            return False

        self.object['group']['parent'][Group] = list()
        return True
    # About Group's Parent

    # About Search Permission
    def DoHavePerm(self, NodeName, UserName):
        group = self.WhatGroup(UserName=UserName)
        if self.DoGroupHavePerm(NodeName, group):
            return True

        if self.DoUserHavePerm(NodeName, UserName):
            return True

        if NodeName in set(self.GetGroupPerm(self.WhatGroup(UserName))):
            return True
        return False

    # About Group's Permission
    def GivePermToGroup(self, NodeName, GroupName):
        if not GroupName in self.object["group"]["permset"]:
            self.object["group"]["permset"][GroupName] = list()
        
        if not False in list(a in set(self.object["group"]["permset"][GroupName]) for a in self.__re(self.object['permission']['list'].values(), NodeName)):
            return True

        if False in list(a in set(self.object["permission"].values()) for a in self.__re(self.object['permission']['list'].values(), NodeName)):
            return False

        var = self.__re(self.object['permission']['list'].values(), NodeName)
        Ivar = self.__re(self.object['permission']['list'].values(), NodeName)
        for i in range(len(var)):
            if var[i] in set(self.object['group']['permset'][GroupName]):
                del Ivar[i]
        self.object["group"]["permset"][GroupName] += Ivar
        return True

    def RemovePermFromGroup(self, NodeName, GroupName):
        if GroupName not in set(self.object["group"]["permset"].keys()):
            return False

        if NodeName not in set(self.object["group"]["permset"][GroupName]):
            return False

        self.object["group"]["permset"][GroupName].remove(NodeName)
        return True

    def DoGroupHavePerm(self, NodeName, GroupName):
        if GroupName not in self.object['group']['list'].keys():
            return False

        if NodeName in set(self.object['group']['permset'][GroupName]):
            return True

        return False

    def __GroupPermList(self, GroupName):
        if GroupName not in set(self.object["group"]['list'].keys()):
            return False
        
        if GroupName not in set(self.object['group']['permset'].keys()) and GroupName not in set(self.object['group']['parent'].keys()):
            self.object['group']['permset'][GroupName] = list()
        
        return self.object['group']['permset'][GroupName]

    def __GroupParentPerm(self, GroupName):
        # recoding.
        if self.GetParent(GroupName) != False:
            #IReturn = [self.GroupPermList(local) for local in self.GetParent(GroupName)]
            IReturn = []
            Parent = self.GetParent(GroupName)
            for i in range(len(Parent)):
                IReturn += self.__GroupPermList(Parent[i])
                # 获取父组所拥有权限,在获取父组的父组
                # 这里获取父组所拥有权限
                PaP = self.GetParent(Parent[i])
                if PaP == False or PaP == []:
                    continue
                # 因为技术原因,EP只支持两层的继承组
            return IReturn
        '''
        Need = self.GetParent(GroupName)
        if Need != False:
            IReturn = list()
            DoneList = list()
            while True:
                IBreak = False
                for i in range(len(Need)):
                    if Need[i] in DoneList:
                        break
                    It = self.__GroupPermList(Need[i])
                    # It就是现在循环的这个组所拥有的权限
                    IReturn += It
                    IReturn = list(set(IReturn))
                    DoneList.append(Need[i])
                    if self.GetParent(Need[i]) != False:
                        Need += self.GetParent(Need[i])
                        Need = list(set(Need))
                        break

                if IBreak == True:
                    break
        '''
        return False

    def GetGroupPerm(self, GroupName):
        IReturn = list()
        if self.__GroupPermList(GroupName) != False:
            IReturn += list(self.__GroupPermList(GroupName))
        if self.__GroupParentPerm(GroupName):
            IReturn += list(self.__GroupParentPerm(GroupName))
        if IReturn == list():
            return False
        return IReturn

    def DoGroupParentHavePerm(self, NodeName, GroupName):
        # Group Parent
        if self.GetParent(GroupName) is list():
            for i in range(len(self.GetParent(GroupName))):
                self.DoGroupHavePerm(NodeName, self.GetParent(GroupName)[i])

    # About Group's Permission

    # About Group and User
    def UserJoinToGroup(self, UserName, GroupName):
        if UserName not in set(self.object['group']['user'].keys()):
            self.object['group']['user'][UserName] = []

        if GroupName not in set(self.object['group']['list'].keys()):
            return False

        if GroupName == self.object['group']['user'][UserName]:
            return True

        self.object['group']['user'][UserName] = GroupName
        return self.object['group']['user'][UserName]

    def RemoveUserFromGroup(self, UserName, GroupName):
        if GroupName not in set(self.object['group']['user'].values()):
            return False

        if UserName not in set(self.object['group']['user'].keys()):
            return False

        del self.object['group']['user'][UserName]
        return True

    def ReJoin(self, UserName, NewGroupName):
        if UserName not in set(self.object['group']['user'].keys()):
            return False

        if NewGroupName not in set(self.object['group']['list'].keys()):
            return False

        self.object['group']['user'][UserName] = NewGroupName
        return True
    # About Group and Userw

    def Check(self):
        for i in self.object['group']['permset'].keys():
            for ii in range(len(self.object['group']['permset'][i])):
                print(self.object['group']['permset'][i])
                if self.object['group']['permset'][i][ii - 1] not in self.object['permission']['list'].values():
                    del self.object['group']['permset'][i][ii - 1]

    # About Disable and Enable

    def GetAllowObject(self):
        return self.object['permission']['nodeallow']

    def SetPermToEnable(self, Node):
        if Node not in self.GetNodeList():
            return False
        AllowObject = self.GetAllowObject()
        AllowObject[Node] = True
        return AllowObject[Node] == True

    def SetPermToDisable(self, Node):
        if Node not in self.GetNodeList():
            return False
        AllowObject = self.GetAllowObject()
        AllowObject[Node] = False
        return AllowObject[Node] == False

    # About Disable and Enable

    # About Many Keys Bind
    def GetBindObject(self):
        return self.object['permission']['binding']

    def BindKey(self, Key, Node):
        if Node not in self.GetNodeList():
            return False

        if Key in self.GetBindObject().keys():
            return False

        if Node == None:
            return False

        self.object['permission']['binding'][Key] = Node
        return self.GetNodeList()[Key] == Node

    def UnBind(self, Key):
        if Key not in self.GetBindObject().keys():
            return False

        del self.object['permission']['binding'][Key]
        return True

    def ReBind(self, Key, Node):
        if Node not in self.GetNodeList():
            return False

        if Node == None:
            self.UnBind(Key)
            return True

        self.object['permission']['binding'][Key] = Node
        return self.GetNodeList()[Key] == Node
    # About Many Keys Bind